package com.yirui.serialcomm.core.parse;

import com.yirui.serialcomm.core.domain.SerialCommPacket;
import com.yirui.serialcomm.core.domain.SimpleSerialCommPacket;
import com.yirui.serialcomm.core.domain.StreamType;
import com.yirui.serialcomm.core.util.HexUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 简单的按头信息+内容长度+内容打包与解包处理
 * @author Dujie
 * @create 2025/8/13
 * @since 1.0.0
 */
@Slf4j
public class SimplePacketParser implements PacketParser{
    // 协议常量
    public static final byte[] HEADER = {0x55, (byte)0xAA, 0x12, 0x34};
    private static final int HEADER_LEN = HEADER.length;
    private static final int MAX_LEN = 64*1024;

    public <T> T decode(InputStream inputStream) throws IOException {
        return (T) getNextPacket(getBodyLength(inputStream), inputStream);
    }

    // 发送数据（简化协议）
    public byte[]  encode(SerialCommPacket data) throws IOException {
        if(log.isDebugEnabled()){
            log.debug("收到[{}]数据写入串口管道: {}" , data.getType(), HexUtils.toHexString(data.getData()));
        }
        try(ByteArrayOutputStream packet = new ByteArrayOutputStream()) {
            //写入头
            encodeHeaders(data, packet);
            //类型+内容长度
            encodeDataLength(data.getSize(), packet);
            //写入类型
            encodeDataType(data, packet);
            // 写入数据
            encodeData(data, packet);
            return packet.toByteArray();
        }
    }

    protected void encodeDataLength(int size, ByteArrayOutputStream packet) {
        // 写入长度（大端序）
        packet.write((size >> 8) & 0xFF);
        packet.write(size & 0xFF);
    }

    protected void encodeData(SerialCommPacket data, ByteArrayOutputStream packet) throws IOException {
        // 写入数据
        packet.write(data.getData());
    }

    protected void encodeDataType(SerialCommPacket data, ByteArrayOutputStream packet) {

    }

    protected void encodeHeaders(SerialCommPacket data, ByteArrayOutputStream packet) throws IOException {
        // 写入头
        packet.write(HEADER);
    }

    private static byte[] getNextPacket(int expectedLength, InputStream inputStream) throws IOException {

        if(expectedLength>0){
            if(expectedLength>MAX_LEN){
                throw new IOException("MC包内容长度超出最大限制:"+expectedLength);
            }
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            int b;
            while(expectedLength-->0 && (b = inputStream.read())!=-1){
                outputStream.write(b);
            }
            if(outputStream.size() == 0){
                throw new IOException("MC包内容无法获取!");
            }else{
                return outputStream.toByteArray();
            }

        }else{
            throw new IOException("MC包头中描述的内容长度无效!");
        }

    }

    private static int getBodyLength(InputStream inputStream) throws IOException {
        return ((inputStream.read() & 0xFF) << 8) |
                (inputStream.read() & 0xFF);
    }




    // 查找下一个 MC 头 ({0x55, (byte)0xAA, 0x12, 0x34})，不读取多余数据
    public boolean matchHeader(InputStream inputStream) {
        try {
            int readByte, bufferPosition = 0;
            while ((readByte = inputStream.read()) != -1) {
                // 寻找头阶段
                if (bufferPosition < HEADER_LEN) {

                    if ((byte)readByte != HEADER[bufferPosition]) {
                        bufferPosition = 0; // 不匹配则重置
                        continue;
                    }
                    bufferPosition++;

                    if (bufferPosition == HEADER_LEN) {
                        return true;
                    }
                }
            }
            return false;
        } catch (IOException e) {
            return false;
        }
    }
}
